﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ExpreRec.Logic.Expression;
using ExpreRec.Logic.Model;
using System.IO;
using System.Threading;

namespace ExpreRec.UI
{
    public partial class TrainingPreprocessForm : Form
    {
        private delegate void refreshActionType(int p);
        private delegate void finishActionType(bool manualStop);

        private bool threadRunningFlag = false;

        private string folderName;
        private IList<string> expressionTypes;

        private IList<PictureItem> pictureItems;
        private int processed;

        private IDictionary<string, int> statisticsIndex = new Dictionary<string, int>();

        private Thread innerThread;
        private refreshActionType refreshAction;
        private finishActionType finishAction;

        private bool closingFlag = false;

        public string FolderName
        {
            set { folderName = value; }
        }

        private static Classification classifier = new Classification();

        public TrainingPreprocessForm()
        {
            InitializeComponent();
            refreshAction = new refreshActionType(updateUI);
            finishAction = new finishActionType(finished);
        }

        private void TrainingPreprocessForm_Load(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Maximized;
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            KeyValuePair<IList<string>, IList<PictureItem>> res = classifier.ListPictures(folderName);

            expressionTypes = res.Key;

            pictureItems = res.Value;

            if (expressionTypes.Count != 0 && pictureItems.Count != 0)
            {
                buttonStart.Enabled = false;
                buttonStop.Enabled = true;
                buttonNextStep.Enabled = false;

                IDictionary<string, int> statistics = new Dictionary<string, int>();
                listViewFiles.Groups.Clear();
                listViewFiles.Items.Clear();
                listViewStatistics.Items.Clear();

                processed = 0;

                statisticsIndex.Clear();
                progressBarProcess.Value = 0;

                foreach (string label in expressionTypes)
                {
                    listViewFiles.Groups.Add(label, label);
                    statistics.Add(new KeyValuePair<string, int>(label, 0));
                }

                for (int i = 0; i < pictureItems.Count; i++)
                {
                    PictureItem item = pictureItems[i];
                    ListViewItem listViewItem = new ListViewItem(item.Label + "\\" + Path.GetFileName(item.FileName), listViewFiles.Groups[item.Label]);
                    listViewFiles.Items.Add(listViewItem);
                    statistics[item.Label]++;
                }

                int cnt = 0;

                foreach (string label in expressionTypes)
                {
                    ListViewItem item = new ListViewItem();
                    item.Text = label;

                    item.SubItems.Add(statistics[label].ToString());
                    item.SubItems.Add(statistics[label].ToString());

                    listViewStatistics.Items.Add(item);

                    statisticsIndex[label] = cnt++;
                }

                labelNextFileAddress.Text = pictureItems[0].FileName;

                threadRunningFlag = true;

                innerThread = new Thread(new ThreadStart(threadMain));
                innerThread.Name = "InnerThread";
                innerThread.Start();
            }
            else
            {
                MessageBox.Show("图片库地址有误，请重新选择！");
            }
        }

        private void buttonNextStep_Click(object sender, EventArgs e)
        {
            ((MainForm)this.MdiParent).ShowForm(new KNNTrainingForm());
            //this.Close();
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            buttonStop.Enabled = false;
            threadRunningFlag = false;
        }

        protected void updateUI(int p)
        {
            if (p != pictureItems.Count - 1)
                labelNextFileAddress.Text = pictureItems[p + 1].FileName;
            else labelNextFileAddress.Text = "已完成";

            listViewFiles.Items.RemoveAt(0);

            int now = int.Parse(listViewStatistics.Items[statisticsIndex[pictureItems[p].Label]].SubItems[2].Text);
            listViewStatistics.Items[statisticsIndex[pictureItems[p].Label]].SubItems[2].Text = (--now).ToString();

            processed++;

            progressBarProcess.Value = processed * progressBarProcess.Maximum / pictureItems.Count;
        }

        protected void finished(bool manualStop)
        {
            if (!closingFlag)
            {
                buttonStart.Enabled = true;
                buttonNextStep.Enabled = true;
                buttonStop.Enabled = false;


                if (manualStop)
                    MessageBox.Show("预处理操作被终止，但您也可以进入下一步！");
                else
                    MessageBox.Show("预处理操作全部结束，请进入下一步！");
            }
        }

        private void threadMain()
        {
            for (int i = 0; i < pictureItems.Count; i++)
            {
                if (!threadRunningFlag)
                {
                    if (!closingFlag)
                        this.Invoke(finishAction, new object[] { true });
                    return;
                }

                classifier.GaborKNNPreProcess(pictureItems[i]);

                if (threadRunningFlag)
                {
                    this.Invoke(refreshAction, new object[] { i });
                }
            }
            this.Invoke(finishAction, new object[] { false });
            threadRunningFlag = false;
        }

        private void TrainingPreprocessForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            closingFlag = true;
            if (threadRunningFlag)
            {
                threadRunningFlag = false;

                Thread.Sleep(100);
            }
        }
    }
}
